package com.gome.ocean.service.diamond;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.client.methods.HttpGet;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

import com.gome.ocean.common.utils.HttpClientUtil;


/**
 * 通知服务，用于通知其他节点
 * 
 * @author boyan
 * @date 2010-5-6
 */
@Component
public class NotifyService implements InitializingBean, DisposableBean {

    private static final Log      log               = LogFactory.getLog(NotifyService.class);

    private static final String   URL_PREFIX        = "/diamond-server/notify.do";
    private static final String   PROTOCOL          = "http://";
    private static final String   DEFAULT_USER_HOME = System.getProperty("user.home");
    private static String         diamond_path      = DEFAULT_USER_HOME.concat("/diamond");
    private volatile List<String> domainNameList    = new LinkedList<String>();
    private final AtomicInteger   domainNamePos     = new AtomicInteger(0);

    @Override
    public void destroy() throws Exception {
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        reloadServerAddresses(); // 加载服务地址
        randomDomainNamePos();// 设置随机服务下标
    }

    private void randomDomainNamePos() {
        Random rand = new Random();
        List<String> domainList = this.domainNameList;
        if (!domainList.isEmpty()) {
            this.domainNamePos.set(rand.nextInt(domainList.size()));
        }
    }

    private void reloadServerAddresses() {
        FileInputStream fis = null;
        InputStreamReader reader = null;
        BufferedReader bufferedReader = null;
        try {
            File serverAddressFile = new File(generateLocalFilePath(diamond_path, "ServerAddress"));
            if (!serverAddressFile.exists()) {
                return;
            }
            fis = new FileInputStream(serverAddressFile);
            reader = new InputStreamReader(fis);
            bufferedReader = new BufferedReader(reader);
            String address = null;
            while ((address = bufferedReader.readLine()) != null) {
                address = address.trim();
                if (StringUtils.isNotBlank(address)) {
                    domainNameList.add(address);
                }
            }
            bufferedReader.close();
            reader.close();
            fis.close();
        } catch (Exception e) {
            log.error("查找diamond服务地址出错！", e);
        } finally {
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (Exception e) {

                }
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (Exception e) {

                }
            }
            if (fis != null) {
                try {
                    fis.close();
                } catch (Exception e) {

                }
            }
        }
    }

    private String generateLocalFilePath(String directory, String fileName) {
        String sign = "";
        if (StringUtils.isEmpty(directory)) directory = System.getProperty("user.home");
        if (directory.endsWith("\\") || directory.endsWith("/")) sign = "";
        else sign = "/";
        return directory.concat(sign).concat(fileName);
    }

    /**
     * 通知配置信息改变
     * 
     * @param md5
     * @param id
     */
    public void notifyConfigInfoChange(String dataId, String group, String md5) {
        String ipaddr = domainNameList.get(this.domainNamePos.get());
        String urlString = generateNotifyConfigInfoPath(dataId, group, ipaddr, md5);
        HttpClientUtil httpClientUtil = new HttpClientUtil();
        try {
            URL url = new URL(urlString);
            HttpGet httpGet = HttpClientUtil.getGetRequest();
            httpGet.setURI(url.toURI());
            String result = httpClientUtil.executeAndGetWithFailedRetry(httpGet, 6, 1000l);
            log.info("通知节点" + ipaddr + "分组信息改变：" + result);
        } catch (Exception e) {
            log.error("http调用失败,url=" + urlString, e);
        }
    }

    private String generateNotifyConfigInfoPath(String dataId, String group, String address, String md5) {
        StringBuffer url = new StringBuffer();
        url.append(PROTOCOL)
            .append(address)
            .append(URL_PREFIX)
            .append("?method=notifyConfigInfo&dataId=")
            .append(dataId)
            .append("&group=")
            .append(group)
            .append("&md5=")
            .append(StringUtils.isEmpty(md5) ? "" : md5);
        return url.toString();
    }
}
